home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / dev / cross / devpic.lha / picasm-src / pic14bit.c < prev    next >
C/C++ Source or Header  |  1998-04-19  |  6KB  |  254 lines

  1. /*
  2.  * picasm -- pic14bit.c
  3.  *
  4.  * Timo Rossi <trossi@iki.fi>
  5.  * 
  6.  */
  7.  
  8. #include <stdio.h>
  9.  
  10. #include "picasm.h"
  11.  
  12. /*
  13.  * Assemble 14-bit PIC code
  14.  */
  15. int
  16. assemble_14bit_mnemonic(int op)
  17. {
  18.   long val;
  19.   struct symbol *sym;
  20.   char *cp;
  21.   int t, symtype;
  22.  
  23.   switch(op) {
  24.     case KW_SUBLW:
  25.     case KW_ANDLW:
  26.     case KW_IORLW:
  27.     case KW_XORLW:
  28.       val = get_expression();
  29.       if(expr_error)
  30.     return FAIL;
  31.       if(val < -0x80 || val > 0xff)
  32.     error(0, "8-bit literal out of range");
  33.       val &= 0xff; /* this assumes 2-complement negative numbers */
  34.       switch(op) {
  35.         case KW_SUBLW: gen_code(0x3c00 | val); break;
  36.     case KW_ANDLW: gen_code(0x3900 | val); break;
  37.     case KW_IORLW: gen_code(0x3800 | val); break;
  38.     case KW_XORLW: gen_code(0x3a00 | val); break;
  39.       }
  40.       break;
  41.  
  42.     case KW_ADDLW:
  43.       if(gen_byte_c(0x3e00) != OK)
  44.     return FAIL;
  45.       break;
  46.  
  47.     case KW_MOVLW:
  48.       if(gen_byte_c(0x3000) != OK)
  49.     return FAIL;
  50.       break;
  51.  
  52.     case KW_ADDWF:
  53.     case KW_SUBWF:
  54.     case KW_ANDWF:
  55.     case KW_IORWF:
  56.     case KW_XORWF:
  57.     case KW_COMF:
  58.     case KW_DECF:
  59.     case KW_INCF:
  60.     case KW_MOVF:
  61.     case KW_DECFSZ:
  62.     case KW_INCFSZ:
  63.     case KW_RLF:
  64.     case KW_RRF:
  65.     case KW_SWAPF:
  66.       val = get_expression();
  67.       if(expr_error)
  68.     return FAIL;
  69.       if(val < 0 || val > 0x7f)
  70.     error(0, "Register file address out of range");
  71.       t = 1;
  72.       if(token_type == TOK_COMMA) {
  73.     get_token();
  74.     t = get_expression();
  75.     if(expr_error)
  76.       return FAIL;
  77.       }    else {
  78.     if(warnlevel > 0)
  79.       warning("Destination speficier omitted");
  80.       }
  81.  
  82.       val = (val & 0x7f) | (t != 0 ? 0x80 : 0);
  83.       switch(op) {
  84.         case KW_ADDWF:  gen_code(0x0700 | val); break;
  85.     case KW_SUBWF:  gen_code(0x0200 | val); break;
  86.     case KW_ANDWF:  gen_code(0x0500 | val); break;
  87.     case KW_IORWF:  gen_code(0x0400 | val); break;
  88.     case KW_XORWF:  gen_code(0x0600 | val); break;
  89.     case KW_COMF:   gen_code(0x0900 | val); break;
  90.     case KW_DECF:   gen_code(0x0300 | val); break;
  91.     case KW_INCF:   gen_code(0x0a00 | val); break;
  92.     case KW_MOVF:   gen_code(0x0800 | val); break;
  93.     case KW_DECFSZ: gen_code(0x0b00 | val); break;
  94.     case KW_INCFSZ: gen_code(0x0f00 | val); break;
  95.     case KW_RLF:    gen_code(0x0d00 | val); break;
  96.     case KW_RRF:    gen_code(0x0c00 | val); break;
  97.     case KW_SWAPF:  gen_code(0x0e00 | val); break;
  98.       }
  99.       break;
  100.  
  101.     case KW_CLRF:
  102.     case KW_MOVWF:
  103.       val = get_expression();
  104.       if(expr_error)
  105.     return FAIL;
  106.       if(val < 0 || val > 0x7f)
  107.     error(0, "Register file address out of range");
  108.       switch(op) {
  109.         case KW_CLRF:  gen_code(0x0180 | val); break;
  110.     case KW_MOVWF: gen_code(0x0080 | val); break;
  111.       }
  112.       break;
  113.  
  114.     case KW_BCF:
  115.     case KW_BSF:
  116.     case KW_BTFSC:
  117.     case KW_BTFSS:
  118.       val = get_expression();
  119.       if(expr_error)
  120.     return FAIL;
  121.       if(val < 0 || val > 0x7f)
  122.     error(0, "Register file address out of range");
  123.       if(token_type != TOK_COMMA) {
  124.     error(1, "',' expected");
  125.     return FAIL;
  126.       }
  127.       get_token();
  128.       t = get_expression();
  129.       if(expr_error)
  130.     return FAIL;
  131.       if(t < 0 || t > 7) {
  132.     error(0, "Bit number out of range");
  133.       }
  134.       val |= (t << 7);
  135.       switch(op) {
  136.         case KW_BCF:   gen_code(0x1000 | val); break;
  137.     case KW_BSF:   gen_code(0x1400 | val); break;
  138.     case KW_BTFSC: gen_code(0x1800 | val); break;
  139.     case KW_BTFSS: gen_code(0x1c00 | val); break;
  140.       }
  141.       break;
  142.  
  143.     case KW_CALL:
  144.     case KW_GOTO:
  145.       t = 0;
  146.       if(token_type == TOK_IDENTIFIER || token_type == TOK_LOCAL_ID) {
  147.     symtype =
  148.       (token_type == TOK_IDENTIFIER ? SYMTAB_GLOBAL : SYMTAB_LOCAL);
  149.  
  150.     if(symtype == SYMTAB_LOCAL && local_level == 0) {
  151.       error(1, "Local symbol outside a LOCAL block");
  152.       return FAIL;
  153.     }
  154.  
  155.     sym = lookup_symbol(token_string, symtype);
  156.     if(sym == NULL || sym->type == SYM_FORWARD) {
  157.       if(sym == NULL) {
  158.         sym = add_symbol(token_string, symtype);
  159.         sym->type = SYM_FORWARD;
  160.       }
  161.  
  162.       val = 0;
  163.       add_patch(symtype, sym, PATCH11);
  164.       t = 1;
  165.       get_token();
  166.       goto gen_goto_call;
  167.     }
  168.       }
  169.  
  170.       val = get_expression();
  171.       if(expr_error)
  172.     return FAIL;
  173.       if(val < 0 || val >= prog_mem_size)
  174.     error(0, "GOTO/CALL address out of range");
  175. gen_goto_call:
  176.       val &= 0x7ff;
  177.       switch(op) {
  178.         case KW_CALL: gen_code(0x2000 | val); break;
  179.     case KW_GOTO: gen_code(0x2800 | val); break;
  180.       }
  181.       if(t)
  182.     list_flags |= LIST_FORWARD;
  183.     break;
  184.  
  185.     case KW_TRIS:
  186.       t = get_expression();
  187.       if(expr_error)
  188.     return FAIL;
  189.       if(t < 5 || t > 7)
  190.     error(0, "Invalid register address for TRIS");
  191.       gen_code(0x0060 | t);
  192.       if(warnlevel > 1)
  193.     warning("TRIS instruction not recommended");
  194.       break;
  195.  
  196. /*
  197.  * RETLW allows multiple parameters/strings, for generating lookup tables
  198.  */
  199.     case KW_RETLW:
  200.       for(;;) {
  201.     if(token_type == TOK_STRCONST) {
  202.       for(cp = token_string; *cp != '\0'; cp++)
  203.         gen_code(0x3400 | (int)((unsigned char)(*cp)));
  204.       get_token();
  205.     } else {
  206.       if(gen_byte_c(0x3400) != OK)
  207.         return FAIL;
  208.     }
  209.  
  210.     if(token_type != TOK_COMMA)
  211.       break;
  212.  
  213.     get_token();
  214.       }
  215.       break;
  216.  
  217.     case KW_NOP:
  218.       gen_code(0x0000);
  219.       break;
  220.  
  221.     case KW_CLRW:
  222.       gen_code(0x0100);
  223.       break;
  224.  
  225.     case KW_OPTION:
  226.       gen_code(0x0062);
  227.       if(warnlevel > 1)
  228.     warning("OPTION instruction not recommended");
  229.       break;
  230.  
  231.     case KW_SLEEP:
  232.       gen_code(0x0063);
  233.       break;
  234.  
  235.     case KW_CLRWDT:
  236.       gen_code(0x0064);
  237.       break;
  238.  
  239.     case KW_RETFIE:
  240.       gen_code(0x0009);
  241.       break;
  242.  
  243.     case KW_RETURN:
  244.       gen_code(0x0008);
  245.       break;
  246.  
  247.     default:
  248.       error(1, "Syntax error");
  249.       return FAIL;
  250.   }
  251.   return OK;
  252. }
  253.  
  254.